///////////////////////////////////////////////////////////////////////////////
//	FILENAME:	HotLinks.m
//	SUMMARY:	Implementation of a link-caching Accessory
//	SUPERCLASS:	Object
//	INTERFACE:	HotLinks.nib
//	PROTOCOLS:	<Tool>
//	AUTHOR:		Rohit Khare
//	COPYRIGHT:	(c) 1994 California Institure of Technology, eText Project
///////////////////////////////////////////////////////////////////////////////
//	DESCRIPTION: The HotLinks panel is an example of a loadable
// Accessory, an independent entity within the eText runtime
// environment. The HotLinks panel allows the user to keep a
// quick-reference list of links handy. The object archives itself
// entire in ~/Library/eText/HotLinks (creates the dir if
// nonexistent). We're being lazy, so we'll just write ourselves
// out everytime we're modified -- ideally there's an <appNotification>
// protocol similar to <docNotification>, and we should only save
// this data out on application-quit.
///////////////////////////////////////////////////////////////////////////////
//	HISTORY
//	11/13/94:	Modified to use a storage for sorted hotlink lists.
//	05/06/94:	Created. First actual implementation.
///////////////////////////////////////////////////////////////////////////////

#import "HotLinks.h"

@implementation HotLinks

+ new 
{
	static HotLinks *hl = nil;
	
	if (!hl) {
		hl = [[HotLinks alloc] init];
	}
	return hl;
}

+ toolAwake:theApp
{
	[theApp registerAccessory:NXUniqueString("HotLinks...")
				key:'H'
			   name:NXUniqueString("HotLinks")
			 target:[HotLinks new]
			 action:@selector(activate:)];
	return self;
}

- init
{
	char        buf[MAXPATHLEN];
	NXBundle   *bundle;
	NXStream   *s;
 
 	bundle = [NXBundle bundleForClass:[HotLinks class]];
	if ( [bundle getPath:buf forResource:"HotLinks" ofType:"nib"] ) {
		[NXApp loadNibFile:buf owner:self withNames:NO];
	} else {
		NXLogError("NIB not found: HotLinks");
	}
	[well initLinkWell];
	[panel setFrameAutosaveName:"etHotLinks"];
	[panel setFrameUsingName:"etHotLinks"];
	
	sprintf(buf, "%s/.HotLinks", [userModel stringQuery:ETFDIRECTORY]);
	s = NXOpenTypedStreamForFile(buf, NX_READONLY);
	if (s) {
		anchors = NXReadObject(s);
		NXCloseTypedStream(s);
	} else anchors = [[Storage alloc] initCount:0 elementSize:sizeof(etfLink) description:@encode(etfLink)];
	return self;
}

- free {return self;}

- save
{
	NXStream *s;
	char	 path[MAXPATHLEN];
	
	sprintf(path, "%s/.HotLinks", [userModel stringQuery:ETFDIRECTORY]);
	// need to provide deletion and to load data in init: and to mkdir()
	s = NXOpenTypedStreamForFile(path, NX_WRITEONLY);
	if (s) {
		NXWriteObject(s, anchors);
		NXCloseTypedStream(s);
	}
	return self;
}

- activate:sender
{
	[panel makeKeyAndOrderFront:self];
	[panel makeFirstResponder:browser];
	return self;
}

- delete:sender
{
	int i = [[browser matrixInColumn:0] selectedRow];

	[anchors removeElementAt:i];
	[self save];
	[well setLink:NULL];
	[field setStringValue:""];
	[browser loadColumnZero];
	[self select:browser];
	[panel makeFirstResponder:browser];
    return self;

}

- accept:sender
{
	[anchors insertElement:[sender currentLink] at:0];
	[self save];
	[well setLink:NULL];
	[field setStringValue:""];
	[browser loadColumnZero];
	[self select:browser];
    return self;
}

- rename:sender
{
	int i = [[browser matrixInColumn:0] selectedRow];

	((etfLink *)[anchors elementAt:i])->anchorTitle = NXUniqueString([field stringValue]);
	[self save];
	[browser loadColumnZero];
	[browser setPath:((etfLink *)[anchors elementAt:i])->anchorTitle];
	i = [[browser matrixInColumn:0] selectedRow];
	[well setLink:[anchors elementAt:i]];
	[panel makeFirstResponder:browser];
    return self;
}

- select:sender
{
	int i = [[browser matrixInColumn:0] selectedRow];
	//reflect the selection
	[field setStringValue:((etfLink *)[anchors elementAt:i])->anchorTitle];
	[well setLink:[anchors elementAt:i]];
    return self;
}

static int eTHotLinks_docompare(etfLink *x, etfLink *y)
{
	return strcasecmp(x->anchorTitle, y->anchorTitle);
}

- (int) browser:theBrowser fillMatrix:theMatrix inColumn:(int) col 
{
	int		rows,i;
	id		cell;
	
	rows = [anchors count];
	qsort(anchors->dataPtr, anchors->numElements, anchors->elementSize, eTHotLinks_docompare);
	for (i=0; i <rows; i++) {
		[theMatrix addRow];
		cell = [theMatrix cellAt:i :0];
		[cell setStringValueNoCopy:((etfLink *)[anchors elementAt:i])->anchorTitle];
		[cell setLoaded:YES];
		[cell setLeaf:YES];
	}
	return rows;
}
@end